package com.naiterui.ehp.bs.file.utils;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpHeaders;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import com.naiterui.ehp.bp.utils.encypt.MD5;
import com.naiterui.ehp.bp.utils.net.IPUtil;
import com.naiterui.ehp.bs.file.api.common.FileConstant;

/**
 * 文件存储工具类
 *
 * @author yangfuya
 * @since 2021/9/10
 */
public class FileStoreUtil {

    /**
     * 加密盐
     */
    private static final String SALT = "1233211234567";
    /**
     * 加密控制串的长度
     */
    private static final int EC_LENGTH = 3;
    /**
     * ip二进制转成int
     */
    private static final int IP_BINAR = 4;
    /**
     * ua二进制转成int
     */
    private static final int UA_BINAR = 2;
    /**
     * referer二进制转成int
     */
    private static final int REFERER_BINAR = 1;

    private static final PathMatcher PATH_MATCHER = new AntPathMatcher();

    /**
     * 检查签名
     * 
     * @param ec
     *            加密控制字段
     * @param timestamp
     *            时间戳
     * @param tc
     *            时间校验1.打开 0.关闭
     * @param sign
     *            加密串
     * @param request
     *            用户请求
     */
    public static boolean check(String ec, String timestamp, Integer tc, String sign, HttpServletRequest request) {
        // ec的长度必须为3位
        if (ec.length() != EC_LENGTH) {
            return false;
        }
        // 打开时间校验
        if (tc == FileConstant.TIME_CHECK_OPEN && System.currentTimeMillis() > Long.parseLong(timestamp)) {
            return false;
        }
        String ip = IPUtil.getIp(request);
        String ua = request.getHeader(HttpHeaders.USER_AGENT);
        String referer = request.getHeader(HttpHeaders.REFERER);
        return sign.equals(sign(ec, ip, ua, referer, timestamp));
    }

    /**
     * 签名
     *
     * @param ec
     *            加密控制字段
     * @param ip
     *            用户ip
     * @param ua
     *            user agent
     * @param referer
     *            用户referer
     * @param timestamp
     *            时间戳
     * @return 加密串
     */
    public static String sign(String ec, String ip, String ua, String referer, String timestamp) {
        StringBuilder sb = new StringBuilder();
        // 二进制转int
        int ecInt = Integer.parseInt(ec, 2);
        // 启用ip
        if (isEnable(ecInt, IP_BINAR)) {
            sb.append(ip);
        }
        // 启用ua
        if (isEnable(ecInt, UA_BINAR)) {
            sb.append(ua);
        }
        // 启用referer
        if (isEnable(ecInt, REFERER_BINAR)) {
            sb.append(referer);
        }
        return MD5.md5(sb.append(timestamp).append(SALT).toString());
    }

    /**
     * 获取时间戳
     * 
     * @param timeLength
     *            时长 单位秒
     * @return 指定时间后的时间戳
     */
    public static String getTimestamp(int timeLength) {
        return String.valueOf(System.currentTimeMillis() + (timeLength * 1000L));
    }

    /**
     * 验证该文件是否在白名单或黑名单中
     * 
     * @param list
     *            白名单或黑名单
     * @param uid
     *            文件唯一标识
     * @return boolean
     */
    public static boolean checkWhiteOrBlackList(List<String> list, String uid) {
        return list.stream().anyMatch(uri -> matchUrl(uri, uid));
    }

    private static boolean matchUrl(String matchUrl, String reqUrl) {
        return PATH_MATCHER.match(matchUrl, reqUrl);
    }

    /**
     * 判断是否启用指定的加密
     * 
     * @param source
     *            要判断的数据
     * @param intBinary
     *            转换后的二进制
     * @return boolean
     */
    private static boolean isEnable(int source, int intBinary) {
        return (source & intBinary) == intBinary;
    }
}
